<?php
declare(strict_types=1);
/**
 * Created by project.
 * User: huanzipap
 * Date: 2023/5/10
 * Time: 11:25
 */

namespace App\Controller\Admin;

use App\Controller\AppBaseController;
use App\Model\Act;
use App\Model\ActClockJoin;
use App\Model\ActClockPoint;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use App\Middleware\AdminApiAuth;
use Hyperf\DbConnection\Db;

use PhpOffice\PhpSpreadsheet\IOFactory;

#[Controller(prefix: 'admin')]
#[Middleware(AdminApiAuth::class)]
class ActClockController extends AppBaseController
{
    /**
     * 后台--活动打卡--打卡点|列表
     * @param int $act_id
     * @return object
     */
    #[RequestMapping(path:'actClockPointList/{act_id}',methods: 'get')]
    public function actClockPointList(int $act_id): object
    {
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            $page = $this->request->input('page', 1);
            $limit = $this->request->input('limit', 20);
            $offset = ($page - 1) * $limit;

            //查询条件
            $where = [];
            $where['act_id'] = $act_id;

            $list = ActClockPoint::where($where)->offset($offset)->limit($limit)->get();

            $total = 0;
            $next = 0;
            if($list->isNotEmpty()){
                if($page==1){
                    $total = ActClockPoint::where($where)->count();
                }
                if(count($list) >= $limit) $next = 1;
            }
            return $this->reMsg->re(1,'success',[
                'list' => $list, 'next' => $next, 'total'=>$total
            ]);
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }


    /**
     * 后台--活动打卡--打卡点|详情
     * @param int $point_id
     * @return object
     */
    #[RequestMapping(path:'actClockPointInfo/{point_id}',methods: 'get')]
    public function actClockPointInfo(int $point_id): object
    {
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            $info = ActClockPoint::where('id',$point_id)->first();
            return $this->reMsg->re(1,'success',$info);
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }



    /**
     * 后台--活动打卡--打卡点|编辑
     * @param int|null $point_id
     * @return object
     */
    #[RequestMapping(path: 'actClockPointEdit[/{point_id}]',methods: 'post,get')]
    public function actClockPointEdit(int|null $point_id): object
    {
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);
            $_admin = $checkInfo['data'];

            //获取所有参数
            $data = $this->request->all();

            //虚拟数据
//            if(empty($data)){
//                $data['act_id'] = 4;
//                $data['title'] = '第一次调研';
//                $data['photo'] = '4234223423';
//                $data['position'] = '金源国际大厦';
//            }
            //虚拟数据

            if( empty($data['act_id']) || !is_numeric($data['act_id']) ||
                empty($data['title']) ||
                empty($data['photo']) ||
                empty($data['position'])
            ){
                return $this->reMsg->re(10007,'参数丢失');
            }

            isset($data['status']) && $data['status']==0 ? $data['status'] = 0 : $data['status'] = 1;

            $actInfo = Act::where('id',$data['act_id'])->first();
            if(empty($actInfo)) return $this->reMsg->re(10008);

            //开启事务
            Db::beginTransaction();
            //整理数据
            $insertData['party_id'] = $actInfo->party_id;
            $insertData['act_id'] = $actInfo->id;
            $insertData['title'] = $data['title'];
            $insertData['photo'] = $data['photo'];
            $insertData['position'] = $data['position'];
            $insertData['status'] = $data['status'];

            if($point_id){
                //编辑
                $info = ActClockPoint::where('id',$point_id)->first();
                if(empty($info)) return $this->reMsg->re(10008);
                $info->act_id = $insertData['act_id'];
                $info->title = $insertData['title'];
                $info->photo = $insertData['photo'];
                $info->position = $insertData['position'];
                $info->status = $insertData['status'];

                $info->party_id = $actInfo->party_id;
                $info->admin_id = $_admin->id;
                $info->save();
            }else{
                //新建
                $insertData['party_id'] = $actInfo->party_id;
                $insertData['admin_id'] = $_admin->id;
                ActClockPoint::create($insertData);
            }
            Db::commit();
            return $this->reMsg->re(1);
        }catch (\Exception $exception){
            Db::rollBack();
            return $this->diyError->errorJson($exception);
        }
    }



    /**
     * 后台--活动打卡--打卡点|删除
     * @param int $point_id
     * @return object
     */
    #[RequestMapping(path:'actClockPointDelete/{point_id}',methods: 'get')]
    public function actClockPointDelete(int $point_id): object
    {
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            //判断信息
            $info = ActClockPoint::where('id',$point_id)->first();
            if(empty($info)) return $this->reMsg->re(10008);

            //删除问题
            $info->delete();
            return $this->reMsg->re(1);
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }


    /**
     * 后台--活动打卡--打卡点|打卡排行榜
     * @param int $act_id
     * @return object
     */
    #[RequestMapping(path: 'actClockRankList/{act_id}',methods: 'post,get')]
    public function actClockRankList(int $act_id): object{
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            //判断信息
            $info = Act::where('id',$act_id)->first();
            if(empty($info)) return $this->reMsg->re(10008);

            $page = $this->request->input('page', 1);
            $limit = $this->request->input('limit', 20);
            $offset = ($page - 1) * $limit;


            $where['act_id'] = $info->id;
            $list = ActClockJoin::with(['user'=>function ($query) {
                    $query->selectRaw('id,avatar,auth_name')->get();
                }])->where('act_id',$info->id)
                ->selectRaw('id,uid,count(id) as clock_count,created_at')
                ->groupBy('uid')
                ->orderByDesc('clock_count')
                ->orderBy('created_at')
                ->offset($offset)
                ->limit($limit)
                ->get();

            $total = 0;
            $next = 0;
            if($list->isNotEmpty()){
                if($page==1){
                    $total = ActClockJoin::where($where)->count();
                }
                if(count($list) >= $limit) $next = 1;
            }
            return $this->reMsg->re(1,'success',[
                'list' => $list, 'next' => $next, 'total'=>$total
            ]);
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }



    /**
     * 后台--活动打卡--打卡人列表
     * @param int $point_id
     * @return object
     */
    #[RequestMapping(path: 'actClockUserList/{point_id}',methods: 'post,get')]
    public function actClockUserList(int $point_id): object{
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            //判断信息
            $info = ActClockPoint::where('id',$point_id)->first();
            if(empty($info)) return $this->reMsg->re(10008);

            $page = $this->request->input('page', 1);
            $limit = $this->request->input('limit', 20);
            $offset = ($page - 1) * $limit;


            $where['point_id'] = $info->id;
            $list = ActClockJoin::with(['user'=>function ($query) {
                    $query->selectRaw('id,avatar,auth_name')->get();
                }])->where($where)
                ->selectRaw('id,uid,title,media_list,status,created_at')
                ->orderBy('created_at')
                ->offset($offset)
                ->limit($limit)
                ->get();

            $total = 0;
            $next = 0;
            if($list->isNotEmpty()){
                if($page==1){
                    $total = ActClockJoin::where($where)->count();
                }
                if(count($list) >= $limit) $next = 1;
            }
            return $this->reMsg->re(1,'success',[
                'list' => $list, 'next' => $next, 'total'=>$total
            ]);
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }



    /**
     * 后台--活动打卡-打卡审核
     * @param int $join_id
     * @return object
     */
    #[RequestMapping(path: 'actClockJoinPass/{join_id}',methods: 'post,get')]
    public function actClockJoinPass(int $join_id): object{
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            //判断信息
            $info = ActClockJoin::where('id',$join_id)->first();
            if(empty($info)) return $this->reMsg->re(10008);

            $status = $this->request->input('status', 2);

            if(empty($status) || !in_array($status, [1,2])) return $this->reMsg->re(0,'异常操作');
            $info->status = $status;
            $info->save();

            return $this->reMsg->re(1,'success');
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }



    /**
     * 后台--活动打卡-打卡删除
     * @param int $join_id
     * @return object
     */
    #[RequestMapping(path: 'actClockJoinDelete/{join_id}',methods: 'post,get')]
    public function actClockJoinDelete(int $join_id): object{
        try{
            //验证管理员信息
            $checkInfo = $this->checkAdmin();
            if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);

            //判断信息
            $info = ActClockJoin::where('id',$join_id)->first();
            if(empty($info)) return $this->reMsg->re(10008);
            $info->delete();
            return $this->reMsg->re(1,'success');
        }catch (\Exception $exception){
            return $this->diyError->errorJson($exception);
        }
    }









    /**
     * 后台-- 活动打卡--打卡点|导入
     * @param int $act_id
     * @return object
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     */
    #[RequestMapping(path: "clockImport/{act_id}", methods: "post")]
    public function clockImport (int $act_id) :object
    {
        //验证管理员信息
        $checkInfo = $this->checkAdmin();
        if($checkInfo['status']==40002) return $this->reMsg->re(10002,$checkInfo['message']);
        $_admin = $checkInfo['data'];

        $info = Act::where('id', $act_id)->first();
        if ($info == null)  return $this->reMsg->re(10008);
        if ($info->type!=1)   return $this->reMsg->re(0,'非答题类型不可导入');

        //判断开始时间
        if($info->start_time && time()<strtotime($info->start_time)) return $this->reMsg->re(0,'活动未开始');
//        //判断结束时间
//        if(time()>strtotime($info->end_time)) return $this->reMsg->re(0,'活动已结束');

        //判断权限
        if($_admin->level!=1 && $info->admin_id!=$_admin->id) return $this->reMsg->re(0,'不可操作其他管理员数据');

        if (isset($activity_info->actionLogs[0]) && $activity_info->actionLogs[0]->admin_id != $_admin->id) {
            return $this->reMsg->re(50013);
        }

        //获取文件
        $file = $this->request->file('file');
        if ($file == null)  return $this->reMsg->re(10007);
        $extension = $file->getExtension();
        if (!in_array($extension, ['xls', 'xlsx'])) {
            return $this->reMsg->re(0,'参数异常');
        }


        //执行导入
        $reader = IOFactory::createReader('Xlsx');
        $reader->setReadDataOnly(TRUE);
        $spreadsheet = $reader->load($file->getPath() . '/' . $file->getFilename());
        $sheet = $spreadsheet->getSheet(0);
        $count_row = $sheet->getHighestRow();
        $count_column = $sheet->getHighestColumn();

        if ($count_row == 0)  return $this->reMsg->re(0,'导入数据为空');

        //获取答题规则
        $actAnswerRuleInfo = ActAnswerRule::where('act_id',$act_id)->first();
        if($actAnswerRuleInfo==null) return $this->reMsg->re(0,'题目异常，答题规则未设置');
//        if($actAnswerRuleInfo->extract_type==2){
//            //随机抽取
//            $hasQuestionCount = ActAnswerQuestion::where('act_id',$act_id)->count();
//            $hasQuestionCount +=$count_row;
//            if($hasQuestionCount < $actAnswerRuleInfo->extract_num) {
//                return $this->reMsg->re(0,'导入数量不可小于抽取数量');
//            }
//        }
//        if($actAnswerRuleInfo->extract_type==3){
//            //指定类型抽取
//            $hasQuestionCount = ActAnswerQuestion::where('act_id',$act_id)->count();
//            $hasQuestionCount +=$count_row;
//            $needQuestionCount = $actAnswerRuleInfo->dan_num + $actAnswerRuleInfo->duo_num + $actAnswerRuleInfo->pan_num;
//            if($hasQuestionCount < $needQuestionCount) {
//                return $this->reMsg->re(0,'导入数量不可小于抽取数量');
//            }
//        }

        if($count_column != 'F') return $this->reMsg->re(0,'导入列异常');

        try {
            Db::beginTransaction();

            for ($row = 2; $row <= $count_row; $row++){
                $_question_title = $sheet->getCell('A' . $row)->getValue();
                if ($_question_title == null) {
                    Db::rollBack();
                    return $this->reMsg->re(0, ['err' => '第' . $row . '行数据异常，题目为空']);
                }

                $_question_type = $sheet->getCell('B' . $row)->getValue();
                if (!in_array($_question_type, [1, 2, 3])) {
                    Db::rollBack();
                    return $this->reMsg->re(0, ['err' => '第' . $row . '行数据异常，题目类型异常']);
                }

                $_answer_list = $sheet->getCell('C' . $row)->getValue();
                $_answer_list_array = $_answer_list != '' ? explode('||', (string) $_answer_list) : [];
                unset($_answer_list);
                if (count($_answer_list_array) == 0) {
                    Db::rollBack();
                    return $this->reMsg->re(0, ['err' => '第' . $row . '行数据异常，答案列表为空']);
                }

                $_true_answer = $sheet->getCell('D' . $row)->getValue();
                $_true_answer_array = $_true_answer != '' ? explode('||', (string) $_true_answer) : [];
                if (count($_true_answer_array) == 0 || count($_true_answer_array) > count($_answer_list_array)) {
                    Db::rollBack();
                    return $this->reMsg->re(0, ['err' => '第' . $row . '行数据异常，正确选项异常']);
                }

                $_question_score = $sheet->getCell('E' . $row)->getValue();
                if (!is_numeric($_question_score)) {
                    Db::rollBack();
                    return $this->reMsg->re(0, ['err' => '第' . $row . '行数据异常，答题分数异常']);
                }


                //实例化题目
                $questionData['party_id'] = $info->party_id;
                $questionData['act_id'] = $act_id;
                $questionData['type'] = $_question_type;
                $questionData['question_title'] = $_question_title;
                $questionData['true_answer_xuan'] = $_true_answer;
                $questionData['score'] = $_question_score;
                $questionData['admin_id'] = $_admin->id;
                $questionInsertRet = ActAnswerQuestion::create($questionData);
                $_insert_data = [];
                foreach ($_answer_list_array as $key => $_answer)
                {
                    $_insert_data[] = [
                        'act_id'=> $act_id,
                        'question_id' => $questionInsertRet->getKey(),
                        'answer_title' => $_answer,
                        'answer_xuan' => $key + 1
                    ];
                }
                Db::table('act_answer_answer')
                    ->insert($_insert_data);
                unset($_insert_data);
            }
            Db::commit();
            return $this->reMsg->re(1);
        } catch (\Exception $exception) {
            Db::rollBack();
            return $this->diyError->errorJson($exception);
        }
    }





}